﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using JCTimes.Portal.Infrastructure;
using JCTimes.DomainModel.Repository;
using JCTimes.DomainModel.Entity;
using JCTimes.Portal.Models;
using JCTimes.Portal.Specification;
using JCTimes.Portal.Models;
using JCTimes.DomainModel.Views;
using System.Data;

namespace JCTimes.Portal.Controllers
{
    [Permission]
    public class AccountController : Controller
    {
        //
        // GET: /Agency/
        private IUserRepository userRep;
        private IPDAFunctionsRepository pfunRep;
        private IPDAUsersFunctionsRepository puserFunRep;
        private IPDARepository pdaRep;
        private const int pageSize = 10;
        private List<ConfigItem> itemlist = new List<Models.ConfigItem>();

        public AccountController(IUserRepository usrRep, IPDAFunctionsRepository pfunRep, IPDAUsersFunctionsRepository puserFunRep, IPDARepository pdaRep)
        {
            this.userRep = usrRep;
            this.pfunRep = pfunRep;
            this.puserFunRep = puserFunRep;
            this.pdaRep = pdaRep;
        }

        public ActionResult Index(string agencyid)
        {
            if (!string.IsNullOrEmpty(agencyid))
            {
                TempData["agencyid"] = agencyid;
            }
            else
            {
                TempData["agencyid"] = null;
            }
            return View();
        }


        /// <summary>
        /// Query users.
        /// </summary>
        /// <param name="pageIndex">Page index.</param>
        /// <param name="searcher">Filter conditions.</param>
        /// <returns>Users grid view</returns>
        public PartialViewResult Grid(int? pageIndex, Searcher searcher)
        {
            UserInfo uinfo = SessionHelper.CurrUser;
            string agencyid = "";
            if (TempData.Peek("agencyid") != null)
            {
                agencyid = TempData.Peek("agencyid").ToString().Trim() ?? "";
            }

            var pred = UserSpecification.Get_V_User_Pred(searcher);
            if (agencyid != "")
            {
                var model = new GridView<V_Users>
                {
                    Searcher = searcher,
                    PagedList = userRep.GetList<V_Users>().Where(pred).Where(m => m.ParentID == agencyid).Where(m => m.RoleID == Constant.Account).OrderByDescending(u => u.CreateDate).ToPagedList(pageIndex ?? 1, pageSize)
                };
                return PartialView("_gridview", model);
            }
            else
            {
                if (uinfo.RoleID == Constant.Admin)
                {
                    var model = new GridView<V_Users>
                    {
                        Searcher = searcher,
                        PagedList = userRep.GetList<V_Users>().Where(pred).Where(m => m.RoleID == Constant.Account).OrderByDescending(u => u.CreateDate).ToPagedList(pageIndex ?? 1, pageSize)
                    };
                    return PartialView("_gridview", model);
                }
                else
                {
                    var model = new GridView<V_Users>
                    {
                        Searcher = searcher,
                        PagedList = userRep.GetList<V_Users>().Where(pred).Where(m => m.RoleID == Constant.Account&&m.ParentID==uinfo.UserID).OrderByDescending(u => u.CreateDate).ToPagedList(pageIndex ?? 1, pageSize)
                    };
                    return PartialView("_gridview", model);
                }
            }
        }

        public ActionResult Create()
        {
            return View(new User { ID = Guid.NewGuid().ToString() });
        }

        /// <summary>
        /// Add user.
        /// </summary>
        /// <param name="user">User item</param>
        /// <returns>Add result in json</returns>
        [HttpPost]
        public JsonResult Create(User user)
        {
            UserInfo uinfo = SessionHelper.CurrUser;
            if (userRep.Find(u => u.UserName == user.UserName) != null)
            {
                return Json(new { Msg = "用户名已存在" });
            }
            try
            {
                user.RoleID = Constant.Account;
                user.CreateDate = DateTime.Now;
                user.Flag = 0;
                if (uinfo.RoleID == Constant.Agency)
                {
                    user.ParentID = uinfo.UserID;
                }
                user.Password = CM.GetMd5Password(System.Configuration.ConfigurationManager.AppSettings["Password"] + "");
                userRep.Add(user);
                userRep.SaveChanges();
                return Json(new { Msg = "创建成功", IsSuccess = true });
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                return Json(new { Msg = "出错了" });
            }
        }

        /// <summary>
        /// Delete user.
        /// </summary>
        /// <param name="id">User id.</param>
        /// <param name="pageIndex">Page index.</param>
        /// <param name="searcher">Filter conditions</param>
        /// <returns></returns>
        public RedirectToRouteResult Delete(string id, int pageIndex, Searcher searcher)
        {
            try
            {
                var user = userRep.Find(id);
                user.Flag = 1;  // 0:Enable, 1: Disable
                userRep.Update(user);
                userRep.SaveChanges();

                //删除客户时将该客户对应的PDA一起删除
                List<PDA> pdalist = userRep.GetList<PDA>().Where(m => m.UsersID == id).ToList();
                if (pdalist != null && pdalist.Count > 0)
                {
                    foreach (PDA pinfo in pdalist)
                    {
                        pdaRep.Delete(pinfo);
                    }

                    pdaRep.SaveChanges();
                }
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
            }
            return RedirectToAction("Grid", new { pageIndex = pageIndex, searcher = searcher });
        }

        /// <summary>
        /// Edit user.
        /// </summary>
        /// <param name="id">User id.</param>
        /// <param name="pageIndex">Page index.</param>
        /// <param name="searcher">Filter condtions.</param>
        /// <returns>User form.</returns>
        public ActionResult Edit(string id, int pageIndex, Searcher searcher)
        {
            TempData["pageIndex"] = pageIndex;
            TempData["searcher"] = searcher;
            //ViewBag.pageIndex = pageIndex;
            //ViewBag.searcher = searcher;
            return View(userRep.Find(id));
        }

        /// <summary>
        /// Edit user.
        /// </summary>
        /// <param name="id">User id.</param>
        /// <param name="pageIndex">Page index.</param>
        /// <param name="searcher">Filter condtions.</param>
        /// <returns>User form.</returns>
        public ActionResult Config(string id)
        {
            TempData["usersID"] = id;
            var funcs = pfunRep.All.OrderBy(f => f.OrderID).ToList(); //系统所有功能
            int count = 0;  //record menu action
            ConfigItem tree = new ConfigItem();
            tree.Items = new List<ConfigItem>();
            tree.Index = count++;
            tree.Text = "所有";
            tree.Parent = null;
            tree.Value = null;

            foreach (var item in funcs.Where(f => f.ParentID == null || f.ParentID == "0"))
            { //1级菜单
                ConfigItem onetemp = new ConfigItem
                {
                    Parent = null,
                    Index = count++,
                    Text = item.FunctionName,
                    Value = item.ID,
                    Checked = pfunRep.IsMatch(id, item.ID),
                };
                int oneIndex = 0;     //record actions exist in view
                tree.Items.Add(onetemp);

                if (funcs.Any(f => f.ParentID == item.ID))
                {
                    onetemp.Items = new List<ConfigItem>();   //2级菜单
                    var funcTwo = funcs.Where(f => f.ParentID == item.ID);

                    foreach (var two in funcTwo)
                    {
                        bool ischeck = pfunRep.IsMatch(id, two.ID);
                        ConfigItem twotemp = new ConfigItem
                        {
                            Parent = onetemp,
                            Index = oneIndex++,
                            Text = two.FunctionName,
                            Value = two.ID,
                            Checked = ischeck,
                        };
                        int twoIndex = 0;
                        onetemp.Items.Add(twotemp);

                        if (ischeck && (!onetemp.Checked || !tree.Checked))
                        {
                            //checked parent item if any of its children is checked
                            //when display the tree
                            if (!onetemp.Checked) { onetemp.Checked = true; }

                            if (!tree.Checked) { tree.Checked = true; }
                        }

                        twotemp.Items = new List<Models.ConfigItem>();//3级菜单
                        var functhree = funcs.Where(f => f.ParentID == two.ID);

                        foreach (var three in functhree)
                        {
                            bool ischeckthree = pfunRep.IsMatch(id, three.ID);
                            ConfigItem threetemp = new ConfigItem
                            {
                                Parent = twotemp,
                                Index = twoIndex++,
                                Text = three.FunctionName,
                                Value = three.ID,
                                Checked = ischeckthree,
                            };
                            
                            twotemp.Items.Add(threetemp);

                            if (ischeckthree && (!twotemp.Checked || !tree.Checked))
                            {
                                //checked parent item if any of its children is checked
                                //when display the tree
                                if (!twotemp.Checked) { twotemp.Checked = true; }

                                if (!tree.Checked) { tree.Checked = true; }
                            }

                            int threeIndex = 0;
                            threetemp.Items = new List<Models.ConfigItem>();//4级菜单
                            var funcfour = funcs.Where(f => f.ParentID == three.ID);

                            foreach (var four in funcfour)
                            {
                                bool ischeckfour = pfunRep.IsMatch(id, four.ID);
                                ConfigItem fourtemp = new ConfigItem
                                {
                                    Parent = threetemp,
                                    Index = threeIndex++,
                                    Text = four.FunctionName,
                                    Value = four.ID,
                                    Checked = ischeckfour,
                                };

                                threetemp.Items.Add(fourtemp);

                                if (ischeckfour && (!threetemp.Checked || !tree.Checked))
                                {
                                    //checked parent item if any of its children is checked
                                    //when display the tree
                                    if (!threetemp.Checked) { threetemp.Checked = true; }

                                    if (!tree.Checked) { tree.Checked = true; }
                                }

                                int fourIndex = 0;
                                fourtemp.Items = new List<Models.ConfigItem>();//5级菜单
                                var funcfive = funcs.Where(f => f.ParentID == four.ID);

                                foreach (var five in funcfive)
                                {
                                    bool ischeckfive = pfunRep.IsMatch(id, five.ID);
                                    ConfigItem fivetemp = new ConfigItem
                                    {
                                        Parent = fourtemp,
                                        Index = fourIndex++,
                                        Text = five.FunctionName,
                                        Value = five.ID,
                                        Checked = ischeckfive,
                                    };

                                    fourtemp.Items.Add(fivetemp);

                                    if (ischeckfive && (!fourtemp.Checked || !tree.Checked))
                                    {
                                        //checked parent item if any of its children is checked
                                        //when display the tree
                                        if (!fourtemp.Checked) { fourtemp.Checked = true; }

                                        if (!tree.Checked) { tree.Checked = true; }
                                    }
                                }
                            }

                        }
                    }
                }
            }
            return View(tree);
        }

        /// <summary>
        /// Config role functions.
        /// </summary>
        /// <param name="roleId">Role id.</param>
        /// <param name="TreeView1_checkedNodes">Checked nodes of function tree.</param>
        /// <returns>Role grid.</returns>
        [HttpPost]
        public ActionResult Config(string usersID, List<ConfigItem> TreeView1_checkedNodes)
        {
            foreach (var viewItem in TreeView1_checkedNodes)
            {
                if (viewItem.Text != "所有")
                {
                    AddFunctionRole(usersID, viewItem.Value,viewItem.Text, viewItem);
                }
            }
            return RedirectToAction("Index");
        }

        /// <summary>
        /// Add function to role.
        /// </summary>
        /// <param name="roleID">Role id.</param>
        /// <param name="functionID">Function id.</param>
        /// <param name="viewItem">Config item.</param>
        private void AddFunctionRole(string usersID, string functionID, string functionName, ConfigItem viewItem)
        {
            if (viewItem.Checked == false)
            {  //delete menu item
                PDAUsersFunction frItem = puserFunRep.Find(f => f.PDAFunctionID == functionID && f.UsersID == usersID);
                if (frItem != null)
                {
                    puserFunRep.Delete(frItem);
                    //view actions that is not display in menu
                    var viewaction = pfunRep.All.Where(f => f.ParentID == functionID);
                    if (viewaction != null && viewaction.Count() > 0)
                    {//view actions exists
                        foreach (var act in viewaction)
                        {
                            PDAUsersFunction childfunc = puserFunRep.Find(fr => fr.UsersID == usersID && fr.PDAFunctionID == act.ID);
                            if (childfunc != null)
                            {
                                puserFunRep.Delete(childfunc); //delete view action
                            }
                        }
                    }
                    if (viewItem.Items != null && viewItem.Items.Count() > 0)
                    {
                        foreach (var Levelnd in viewItem.Items)
                        {
                            AddFunctionRole(usersID, Levelnd.Value, Levelnd.Text, Levelnd);
                        }
                    }
                }
            }
            else
            {            //add menu item
                AddFunctionRole(usersID, functionID, functionName);
                //view actions that is not display in menu
                var actions = pfunRep.All.Where(f => f.ParentID == functionID);
                if (actions != null && actions.Count() > 0)
                {
                    foreach (var act in actions)
                    {
                        AddFunctionRole(usersID, act.ID, act.FunctionName);   //add view actions
                    }
                }
                if (viewItem.Items != null && viewItem.Items.Count() > 0)
                {
                    foreach (var Levelnd in viewItem.Items)
                    { //traversing its children
                        AddFunctionRole(usersID, Levelnd.Value, Levelnd.Text, Levelnd);
                    }
                }
            }
            puserFunRep.SaveChanges();
        }

        /// <summary>
        /// Add function to role.
        /// </summary>
        /// <param name="roleID">Role id.</param>
        /// <param name="functionID">Function id.</param>
        private void AddFunctionRole(string usersID, string functionID,string functionName)
        {
            PDAUsersFunction frItem = puserFunRep.Find(f => f.PDAFunctionID == functionID && f.UsersID == usersID);
            if (frItem == null)
            {  //add function if no exist in database
                frItem = new PDAUsersFunction
                {
                    ID = Guid.NewGuid().ToString(),
                    PDAFunctionID = functionID,
                    PDAFunctionName=functionName,
                    UsersID = usersID,
                    CreateDate = DateTime.Now
                };
                puserFunRep.Add(frItem);
            }
            puserFunRep.SaveChanges();
        }

        /// <summary>
        /// Edit user.
        /// </summary>
        /// <param name="id">User id.</param>
        /// <param name="forms">Form collections about user item.</param>
        /// <returns>Edit result, if success then redirect to list, else show validation errors.</returns>
        [HttpPost]
        public ActionResult Edit(string id, FormCollection forms)
        {
            var model = userRep.Find(id);
            if (TryUpdateModel(model))
            {
                try
                {
                    userRep.SaveChanges();
                }
                catch (Exception ex)
                {
                    LogHelper.WriteLog(ex.Message, ex);
                }
                return RedirectToAction("Index");
            }
            return View(model);
        }

        /// <summary>
        /// Reset user password.
        /// </summary>
        /// <param name="id">User id.</param>
        /// <returns></returns>
        [HttpPost]
        public JsonResult Reset(string id)
        {
            var user = userRep.Find(id);
            user.Password = CM.GenDefaultPassword();
            try
            {
                userRep.Update(user);
                userRep.SaveChanges();
                return Json("重置成功", JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                return Json("出错了", JsonRequestBehavior.AllowGet);
            }
        }

        [ActionName("Export")]
        [HttpPost]
        public JsonResult PreExport(Searcher searcher)
        {
            var pred = UserSpecification.Get_V_User_Pred(searcher);

            var list = userRep.GetList<V_Users>().Where(m => m.RoleID == Constant.Account);
            bool hasdata = list.Where(pred).Count() > 0;
            return Json(new { searcher = searcher.ToString(), hasdata = hasdata });
        }


        /// <summary>
        /// Export dismachine report.
        /// </summary>
        /// <param name="searcher">Filter conditions.</param>
        /// <returns>Excel file.</returns>
        public void Export(Searcher searcher)
        {
            var pred = UserSpecification.Get_V_User_Pred(searcher);
            var list = userRep.GetList<V_Users>().Where(m => m.RoleID == Constant.Account);

            var lst = list.Where(pred).OrderByDescending(d => d.CreateDate).ToList();

            string[] filters = new string[] {
                "UserName", "Name","AgencyName", "ContactName", "Tel", "Mobile", "Address", "QQ",
                "Email", "Remark"};

            var dt = lst.ToDataTable(filters);
            string[] columnname = new string[] { "用户名", "客户名称","所属代理商", "联系人名称", "联系方式", "手机", "地址", "QQ", "邮箱", "备注" };

            ExcelHelper.ExportToExcel(null, "客户报表", dt, columnname, filters, false);
        }


        /// <summary>
        /// Get provices by region.
        /// </summary>
        /// <param name="selected">Region name.</param>
        /// <returns>Provinces.</returns>
        public JsonResult GetAccount(string selected)
        {
            var data = userRep.GetAccount(selected)
                //.OrderBy(p => p.ProvinceName)
                             .ToList()
                             .Select(p =>
                                 new
                                 {
                                     label = p.Name,
                                     value = p.ID
                                 })
                             .Distinct();
            return Json(data, JsonRequestBehavior.AllowGet);
        }
    }
}
